package main

/*
 #include <stdlib.h>

typedef void(*SendCallback)(char*);
inline void EndSend(char* response,SendCallback callback){
	callback(response);
}
*/
import "C"
import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"unsafe"
)

type Request struct {
	Data       string              `json:"Data"`
	Headers    map[string][]string `json:"Headers"`
	Method     string              `json:"Method"`
	RequestURI string              `json:"RequestUri"`
}
type Response struct {
	Errors     []string            `json:"Errors"`
	Headers    map[string][]string `json:"Headers"`
	Body       string              `json:"Body"`
	StatusCode int                 `json:"StatusCode"`
}

//export Free
func Free(p unsafe.Pointer) {
	C.free(p)
}

//export Send
func Send(cInput *C.char, callback C.SendCallback) {
	input := C.GoString(cInput)
	var request Request
	var response = &Response{}
	doCallback := func(ret *Response) {
		data, _ := json.Marshal(ret)
		str := string(data)
		C.EndSend(C.CString(str), callback)
	}
	err := json.Unmarshal(([]byte)(input), &request)
	if err != nil {
		response.Errors = append(response.Errors, err.Error())
		doCallback(response)
	} else {
		go func() {
			defer doCallback(response)
			var body io.Reader = nil
			if len(request.Data) > 0 {
				data, de := base64.StdEncoding.DecodeString(request.Data)
				if de != nil {
					response.Errors = append(response.Errors, de.Error())
				} else {
					body = bytes.NewReader(data)
				}
			}
			req, err := http.NewRequest(request.Method, request.RequestURI, body)
			if err != nil {
				response.Errors = append(response.Errors, err.Error())
			} else {
				if request.Headers != nil && len(request.Headers) > 0 {
					for k, values := range request.Headers {
						for _, value := range values {
							req.Header.Set(k, value)
						}
					}
				}
			}
			if response.Errors == nil || len(response.Errors) == 0 {
				transport := &http.Transport{
					DisableKeepAlives: true,
				}
				client := &http.Client{
					Transport: transport,
				}
				resp, err := client.Do(req)
				defer resp.Body.Close()
				if err != nil {
					response.Errors = append(response.Errors, err.Error())
				} else {
					response.Headers = make(map[string][]string)
					response.StatusCode = resp.StatusCode
					for k, v := range resp.Header {
						response.Headers[k] = v
					}
					body, err := ioutil.ReadAll(resp.Body)
					if err != nil {
						response.Errors = append(response.Errors, err.Error())
					} else {
						response.Body = base64.StdEncoding.EncodeToString(body)
					}
				}
			}

		}()
	}
}
func main() {

}
